#pragma once
#include <iostream>
#include "MyTimer.h"
#include "SentDataRecord.h"
#include "ReceivedDataRecord.h"

// GUIState
//
// Class used to represent the GUI State.
//
// The GUIState class contains all the necessary state information to
// drive the GUI.
//
// This includes:
// * In/Out Buffer Putter/Getter Positions
// * Sent/Received Data Records
// * Loaded CSV File Data
// * GUI UI Update Timer

// Use our standard CC3501 namespace
namespace CC3501_Main_GUI {

	using namespace std;
	using namespace System;
	using namespace System::IO;
	using namespace System::Text;
	using namespace System::Diagnostics;
	using namespace System::Collections::Generic;
	using namespace System::Globalization;

	// Class to represent the state of the GUI
	ref class GUIState
	{
	public:
		
		static const int inBufferSize  = 6000;
		static const int outBufferSize = 12000;

		// Constructor
		GUIState(void);

		// Record a sent record
		void addSentRecord(SentDataRecord^);
		
		// Record a received record
		void addReceivedRecord(ReceivedDataRecord^);

		// Get lists of sent/received data
		List<SentDataRecord^>^ getSentDataRecords(void);
		List<ReceivedDataRecord^>^ getReceivedDataRecords(void);

		// Timer methods
		// -------------

		// Get access to the shared timer
		MyTimer^ getTimer(void);

		// Stop timer and reset file position
		void stop(void);

		// Pause the timer
		void pause(void);
		
		// Resume (start if necessary) the timer
		void resume(void);

		// Is the timer running?
		Boolean isRunning(void);
		Boolean hasReachedEndOfFile(void);


		// CSV methods
		// ---------------

		// Set the input CSV file path
		void setInputCSVFilePath(String^);

		// Get the CSV file path
		String^ getInputCSVFilePath(void);

		// Read a line from the csv file
		array<String^>^ readNextLine(void);

		// Read the first column of the next row as a Byte
		Byte^ readFirstColumnOfNextRowAsByte(void);

		// Read the first column of the next row as a UInt16
		UInt16^ readFirstColumnOfNextRowAsUInt16(void);
		
		// Move the file to be at line X
		void setCSVLinePosition(int);
		// Reset the line position, equivalent to setCSVLinePosition(1)
		void resetCSVLinePosition(void);
		
		// Get All lines of csv file
		List<array<String^>^>^ readAllLines(void);

		// Mode methods
		// ---------------

		// Is in calibration mode
		Boolean isInCalibrationMode(void);
		// Is in normal mode
		Boolean isInNormalMode(void);

		// Move between modes of operation
		void setCalibrationMode(void);
		void setNormalMode(void);

		// Status Information
		// ---------------
		
		// In Buffer
		int getInBufferPutterPosition(void);
		void setInBufferPutterPosition(int);

		int getInBufferGetterPosition(void);
		void setInBufferGetterPosition(int);

		int getInBufferSpace(void);
		int getInBufferUsage(void);

		void increaseInBufferPutterPosition(int);

		// Out Buffer
		int getOutBufferPutterPosition(void);
		void setOutBufferPutterPosition(int);

		int getOutBufferGetterPosition(void);
		void setOutBufferGetterPosition(int);

		int getOutBufferSpace(void);
		int getOutBufferUsage(void);
		
		void increaseOutBufferGetterPosition(int);


		// Error Flags
		Boolean isMCUInErrorState(void);
		int getMCUTxErrorCount(void);
		void setMCUTxErrorCount(int);

		// Calibration
		Boolean isCalibrated(void);	

		// Determine the calibration co-efficients
		void performCalibration(void);

		float getCalibrationFactorShakerA(void);
		float getCalibrationFactorShakerB(void);
		
		UInt16 getNextDataIndex(void);

		// Write the sent/received data to a Stream (via Stream Writer)
		void writeToStream(StreamWriter^);

	private:
		// Input CSV file path (nullptr if not yet set)
		String^ inputCSVFilePath;

		// The csv file contents as a list
		// (list of lines, each line is an array of Strings
		List<array<String^>^>^ csvFileAsList;

		// List of sent data records
		List<SentDataRecord^>^ sentDataRecords;

		// List of received data records
		List<ReceivedDataRecord^>^ receivedDataRecords;

		// Converts a CSV file to a list of arrays.
		// Each element in the list represents a row of the csv file.
		// This method will set 'csvFileAsList'
		List<array<String^>^>^ convertCSVFileToList(void);
		
		// The current line of the CSV file
		// Used to perform iteration across the CSV file
		int upToLine;

		// GUI state timer, shared across all GUI interfaces
		MyTimer^ timer;

		// Is the timer running?
		Boolean running;
		
		// Calibration Mode
		Boolean calibrationMode;

		// Is the Device Calibrated
		Boolean calibrated;

		Boolean reachedEndOfFile;

		int inBufferPutterPosition;
		int inBufferGetterPosition;

		int outBufferPutterPosition;
		int outBufferGetterPosition;

		int MCUTxErrorCount;

		float calibrationFactorShakerA;
		float calibrationFactorShakerB;

		unsigned short nextDataIndex;

	};
}

